using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.IO;
using ICSharpCode.SharpZipLib.Zip;
using System.Xml;
using ArchiveMe.Code;

namespace ArchiveMe.Forms
{
    public partial class frmProgress : Form
    {
        private readonly string _startCompressionDir;
        private string direct;
        private int _howManyFiles;
        private int _packLevel = 5;
        private BackgroundWorker _compressionThread;

        public frmProgress(string dirPath)
        {
            InitializeComponent();

            SetDefaultValues();

            _startCompressionDir = dirPath;
        }

        private void SetDefaultValues()
        {
            Text = string.Format("{0} {1}", AppConfig.Name(), AppConfig.Version());

            _howManyFiles = 0;
        }

        private void PrepareCompression()
        {
            DirectoryInfo startDirectoryInfo = new DirectoryInfo(_startCompressionDir);
            string fullPath = Path.GetDirectoryName(_startCompressionDir);

            string hourText = DateTime.Now.Hour.ToString();
            if (DateTime.Now.Hour < 10)
            {
                hourText = "0" + DateTime.Now.Hour;
            }

            string compressedFileName = startDirectoryInfo.Name + "-" + String.Format("{0:yyyy}", DateTime.Now) + String.Format("{0:MM}", DateTime.Now) + String.Format("{0:dd}", DateTime.Now)
                              + "-" + hourText + String.Format("{0:mm}", DateTime.Now) + ".zip";
            if (File.Exists(Application.ExecutablePath + ".cfn"))
            {
                try
                {
                    XmlTextReader reader = new XmlTextReader(Application.ExecutablePath + ".cfn");

                    string node = "";

                    while (reader.Read())
                    {
                        switch (reader.NodeType)
                        {
                            case XmlNodeType.Element:
                                node = reader.Name;
                                break;
                            case XmlNodeType.Text:
                                if (node == "packLevel" && reader.HasValue)
                                {
                                    _packLevel = Convert.ToInt32(reader.Value);
                                }
                                if (node == "fileTheme" && reader.HasValue)
                                {
                                    compressedFileName = reader.Value;
                                    compressedFileName = compressedFileName.Replace("{name}", startDirectoryInfo.Name);
                                    compressedFileName = compressedFileName.Replace("{day}", String.Format("{0:dd}", DateTime.Now));
                                    compressedFileName = compressedFileName.Replace("{month}", String.Format("{0:MM}", DateTime.Now));
                                    compressedFileName = compressedFileName.Replace("{year}", String.Format("{0:yyyy}", DateTime.Now));
                                    compressedFileName = compressedFileName.Replace("{hr}", String.Format("{0}", hourText));
                                    compressedFileName = compressedFileName.Replace("{mm}", String.Format("{0:mm}", DateTime.Now));
                                    compressedFileName = compressedFileName.Replace("{s}", DateTime.Now.Second.ToString());
                                    compressedFileName += ".zip";
                                }
                                break;
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Error occoured", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            direct = fullPath + "\\" + compressedFileName;

            ZipOutputStream wyjscie = new ZipOutputStream(File.Create(direct));

            CalculateFilesToCompres(_startCompressionDir, startDirectoryInfo.Root.ToString());

            compressionProgress.Minimum = 0;
            compressionProgress.Maximum = _howManyFiles;

            DirectoryInfo currentDir = new DirectoryInfo(_startCompressionDir);

            FilesCompression(_startCompressionDir, wyjscie, currentDir.Parent.FullName + "\\");

            wyjscie.Close();

            if (_compressionThread.CancellationPending)
            {
                MessageBox.Show("User abort!");
            }
            else
            {
                MessageBox.Show("Complete!");
            }

            Dispose();

            if (_compressionThread.CancellationPending)
            {
                File.Delete(direct);
            }
        }

        public int FilesCompression(string inFile, ZipOutputStream outFile, string coreDir)
        {
            try
            {
                if (_compressionThread.CancellationPending)
                {
                    return 0;
                }

                outFile.SetLevel(_packLevel);

                string[] allFolders = Directory.GetDirectories(inFile);
                string[] allFiles = Directory.GetFiles(inFile);

                if (allFiles.Length == 0 && inFile != coreDir)
                {
                    string currentFolder = inFile.Replace(coreDir, "");
                    ZipEntry ze = new ZipEntry(currentFolder + "/");
                    outFile.PutNextEntry(ze);
                }

                foreach (string folder in allFolders)
                {
                    if (_compressionThread.CancellationPending)
                    {
                        return 0;
                    }

                    FilesCompression(folder, outFile, coreDir);
                }

                foreach (string file in allFiles)
                {
                    if (_compressionThread.CancellationPending)
                    {
                        return 0;
                    }

                    FileStream strumien = File.OpenRead(file);
                    byte[] bufor = new byte[strumien.Length];

                    strumien.Read(bufor, 0, bufor.Length);
                    strumien.Close();

                    label3.Text = strumien.Name.Replace(coreDir, "");

                    string newFile = file.Replace(coreDir, "");

                    ZipEntry ze = new ZipEntry(newFile);
                    ze.DateTime = File.GetLastWriteTime(file);

                    outFile.PutNextEntry(ze);
                    outFile.Write(bufor, 0, bufor.Length);

                    Application.DoEvents();

                    compressionProgress.Value++;
                }
                return 0;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error occoured", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return 0;
            }
        }

        public void CalculateFilesToCompres(string wejscie, string korzen)
        {
            string[] allFolders = Directory.GetDirectories(wejscie);
            string[] allFiles = Directory.GetFiles(wejscie);

            foreach (string folder in allFolders)
            {
                CalculateFilesToCompres(folder, korzen);
            }
            foreach (string file in allFiles)
            {
                _howManyFiles++;
            }
        }

        private void frmProgress_Load(object sender, EventArgs e)
        {
            _compressionThread.WorkerSupportsCancellation = true;
            _compressionThread.RunWorkerAsync();
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            PrepareCompression();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Are you sure?", "Confirm abort", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                _compressionThread.CancelAsync();
            }
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("mailto:lukasz@gasior.net.pl");

        }
    }
}